package com.yfp.client.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hy.corecode.idgen.WFGIdGenerator;
import com.yfp.client.domain.*;
import com.yfp.client.domain.*;
import com.yfp.client.domain.dto.EnterpriseOrderClientDTO;
import com.yfp.client.domain.dto.EnterpriseOrderComboDTO;
import com.yfp.client.enums.OrderStatus;
import com.yfp.client.mapper.*;
import com.yfp.client.service.*;
import com.yfp.client.mapper.*;
import com.yfp.client.service.*;
import com.yfp.client.util.RedisDistributedLock;
import com.yfp.client.util.RedisKey;
import com.yfp.client.util.ResponseEnum;
import com.yfp.client.util.SecurityUtils;
import com.yfp.common.core.enums.OrderTypeEnum;
import com.yfp.common.core.enums.PackageStatusEnums;
import com.yfp.common.core.enums.PayStatusEnum;
import com.yfp.common.core.enums.PayTypeEnum;
import com.yfp.common.core.utils.DateUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author admin
* @description 针对表【enterprise_order(企业订单)】的数据库操作Service实现
* @createDate 2024-08-10 09:41:36
*/
@Service
@Slf4j
public class EnterpriseOrderServiceImpl extends ServiceImpl<EnterpriseOrderMapper, EnterpriseOrder> implements EnterpriseOrderService {
    @Resource
    private EnterpriseOrderMapper enterpriseOrderMapper;
    @Resource
    private EnterpriseOrderDetailsMapper enterpriseOrderDetailsMapper;
    @Resource
    private EnterpriseOrderClientMapper enterpriseOrderClientMapper;
    @Resource
    public RedisTemplate redisTemplate;
    @Resource
    private WFGIdGenerator wFGIdGenerator;
    @Resource
    private MachineService machineService;
    @Resource
    private ComboService comboService;
    @Resource
    private ImgResourceService imgResourceService;
    @Resource
    private ClientService clientService;
    @Resource
    private TagComboService tagComboService;
    @Resource
    private AreaService areaService;
    @Resource
    private RouteService routeService;
    @Resource
    private PositionService positionService;
    @Resource
    private CompanyService companyService;
    @Resource
    private OrderComboService orderComboService;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    private OrderListService orderListService;
    @Resource
    private ComboMapper comboMapper;
    @Resource
    private ImgResourceMapper imgResourceMapper;

    /**
     * 查询企业订单
     * @param orderSn
     * @return
     */
    @Override
    public EnterpriseOrder findByOrderSn(String orderSn) {
        EnterpriseOrder enterpriseOrder = enterpriseOrderMapper.findByOrderSn(orderSn);
        Timestamp tomorrow = DateUtils.getTomorrow();
        // 订单超时不可用
        if (null == enterpriseOrder && enterpriseOrder.getPayTime().getTime()>tomorrow.getTime()){
            return null;
        }
        List<EnterpriseOrderDetails> enterpriseOrderDetails = enterpriseOrderDetailsMapper.findByEnterpriseOrderSn(orderSn);
        List<String> comboIdList = enterpriseOrderDetails.stream().map(EnterpriseOrderDetails::getComboId).collect(Collectors.toList());
        // 根据套餐id查询套餐
        LambdaQueryWrapper<Combo> comboWrapper = new LambdaQueryWrapper<Combo>().in(Combo::getComboId, comboIdList);
        List<Combo> comboList = comboMapper.selectList(comboWrapper);
        Map<String, Combo> comboMap = comboList.stream().collect(Collectors.toMap(Combo::getComboId, Function.identity()));
        // 获取套餐图片
        List<String> thumbList = comboList.stream().map(Combo::getThumb).collect(Collectors.toList());
        LambdaQueryWrapper<ImgResource> ImgWrapper = new LambdaQueryWrapper<ImgResource>().in(ImgResource::getImgId, thumbList);
        List<ImgResource> imgResourceList = imgResourceMapper.selectList(ImgWrapper);
        Map<String, String> urlMap = imgResourceList.stream().collect(Collectors.toMap(ImgResource::getImgId, ImgResource::getUrl));
        for (EnterpriseOrderDetails enterpriseOrderDetail : enterpriseOrderDetails) {
            Combo combo = comboMap.get(enterpriseOrderDetail.getComboId());
            String url = urlMap.get(combo.getThumb());
            enterpriseOrderDetail.setThumb(url);
        }
        enterpriseOrder.setEnterpriseOrderDetails(enterpriseOrderDetails);
        return enterpriseOrder;
    }

    /**
     * 领取企业订单
     * @param enterpriseOrderClientDTO
     */
    @Override
    @Transactional
    public ResponseEnum enterpriseOrder(EnterpriseOrderClientDTO enterpriseOrderClientDTO) {
        RedisDistributedLock redisDistributedLock = new RedisDistributedLock(redisTemplate, RedisKey.ENTERPRISEORDER, 10);
        try {
            // 加锁
            redisDistributedLock.lock();
            EnterpriseOrder enterpriseOrder = enterpriseOrderMapper.findByOrderSn(enterpriseOrderClientDTO.getOrderSn());
            Timestamp tomorrow = DateUtils.getTomorrow();
            // 订单超时不可用
            if (enterpriseOrder.getPayTime().getTime()>tomorrow.getTime()){
                redisDistributedLock.unlock();
                return ResponseEnum.ENTERPRISEORDER_OUT_TIME;
            }

            List<EnterpriseOrderDetails> enterpriseOrderDetails = enterpriseOrderDetailsMapper.findByEnterpriseOrderSn(enterpriseOrderClientDTO.getOrderSn());
            log.info("enterpriseOrderDetails：{}", enterpriseOrderDetails);
            Map<String, EnterpriseOrderDetails> enterpriseOrderDetailsMap = enterpriseOrderDetails.stream().collect(Collectors.toMap(EnterpriseOrderDetails::getComboId, s -> s));
            List<EnterpriseOrderComboDTO> enterpriseOrderCombos = enterpriseOrderClientDTO.getEnterpriseOrderCombos();

            List<EnterpriseOrderDetails> editOrderDetails = new ArrayList<>();
            List<String> comboIds = new ArrayList<>();
            for (EnterpriseOrderComboDTO enterpriseOrderCombo : enterpriseOrderCombos) {
                // 判断订单套餐剩余是否足够
                EnterpriseOrderDetails enterpriseOrderDetail = enterpriseOrderDetailsMap.get(enterpriseOrderCombo.getComboId());
                log.info("getComboSurplusNum：{}，getComboNum：{}", enterpriseOrderDetail.getComboSurplusNum(), enterpriseOrderCombo.getComboNum());
                if (enterpriseOrderDetail.getComboSurplusNum() < enterpriseOrderCombo.getComboNum()){
                    redisDistributedLock.unlock();
                    return ResponseEnum.ENTERPRISEORDER_COMBO_DEFICIENCY;
                }
                editOrderDetails.add(enterpriseOrderDetail);
                comboIds.add(enterpriseOrderDetail.getComboId());
            }
            double totalDevicePrice = editOrderDetails.stream().mapToDouble(s -> s.getPayMoney().doubleValue()).sum();


            // 设备详情
            Machine machine = machineService.findByMachineId(enterpriseOrder.getMachineId());
            String clientId = SecurityUtils.getClientId();

            Timestamp timestamp = new Timestamp(System.currentTimeMillis());
            // 减订单详情数量
            OrderCombo orderCombo = new OrderCombo();
            orderCombo.setOrderId(String.valueOf(wFGIdGenerator.next()));
            orderCombo.setMachineId(machine.getMachineId());
            orderCombo.setMachineName(machine.getMachineName());
            orderCombo.setUserId(clientId);
            orderCombo.setStatus(OrderStatus.AwaitPackage.getStatus());
            orderCombo.setReplacementState(0);
            orderCombo.setCupboardState(0);
            orderCombo.setCreateTime(timestamp);
            orderCombo.setUpdateTime(timestamp);
            // 设置价格，总价为设备的价格
            orderCombo.setTotalPrice(BigDecimal.valueOf(totalDevicePrice));
            // 设置价格，为用户实际支付的小程序的价格, 如果价格为0，则设置为0.01
            orderCombo.setPrice(totalDevicePrice+"");
            // 商品优惠价格。设备价格-小程序价格
            orderCombo.setAppDiscountMoney(BigDecimal.valueOf(0));
            orderCombo.setEnterpriseOrderSn(enterpriseOrderClientDTO.getOrderSn());
            orderCombo.setCouponDiscountMoney(BigDecimal.valueOf(0));
            List<OrderDetail> orderDetails = new ArrayList<>();
            OrderDetail orderDetail= null;

            List<OrderList> orderLists = new ArrayList<>();
            OrderList orderList = null;
            // 封装orderList数据
            Client client = clientService.getById(clientId);

            Map<String, Combo> ComboMapById = comboService.listByPackageIds(comboIds).stream().collect(Collectors.toMap(Combo::getComboId, payload -> payload));
            Map<String, ImgResource> imgResourceMapById = imgResourceService.listByThumbIds(ComboMapById.values().stream().map(Combo::getThumb).collect(Collectors.toList())).stream().collect(Collectors.toMap(ImgResource::getImgId, payload -> payload));
            Area area = areaService.getById(machine.getAreaId());
            Route route = routeService.getById(machine.getRouteId());
            Position position = positionService.getById(machine.getPositionId());
            Company company = companyService.getById(machine.getCompanyId());

            List<EnterpriseOrderClient> enterpriseOrderClients = new ArrayList<>();

            for (EnterpriseOrderComboDTO enterpriseOrderCombo : enterpriseOrderCombos) {
                EnterpriseOrderClient enterpriseOrderClient = new EnterpriseOrderClient();
                enterpriseOrderClient.setEnterpriseOrderSn(enterpriseOrderClientDTO.getOrderSn());
                enterpriseOrderClient.setEnterpriseOrderDetailsId(enterpriseOrderCombo.getId());
                enterpriseOrderClient.setRemark(enterpriseOrderClientDTO.getRemark());
                enterpriseOrderClient.setComboId(enterpriseOrderCombo.getComboId());
                enterpriseOrderClient.setComboNum(enterpriseOrderCombo.getComboNum());
                enterpriseOrderClient.setClientId(clientId);
                enterpriseOrderClient.setOrderComboId(orderCombo.getOrderId());
                enterpriseOrderClient.setCreateTime(timestamp);
                enterpriseOrderClients.add(enterpriseOrderClient);
                for (int i=0;i<enterpriseOrderCombo.getComboNum();i++){
                    EnterpriseOrderDetails enterpriseOrderDetail = enterpriseOrderDetailsMap.get(enterpriseOrderCombo.getComboId());
                    enterpriseOrderDetailsMapper.subtractComboSurplusNum(enterpriseOrderCombo.getId(), enterpriseOrderCombo.getComboNum());
                    Combo combo = ComboMapById.getOrDefault(enterpriseOrderCombo.getComboId(), new Combo());
                    ImgResource imgResource = imgResourceMapById.getOrDefault(combo.getThumb(), new ImgResource());

                    orderDetail = new OrderDetail();
                    orderDetail.setOrderDetailId(String.valueOf(wFGIdGenerator.next()));
                    orderDetail.setOrderId(orderCombo.getOrderId());
                    orderDetail.setPackageId(enterpriseOrderDetail.getComboId());
                    orderDetail.setPackageName(enterpriseOrderDetail.getComboName());
                    orderDetail.setIsHeatAdditive(true);
                    orderDetail.setHeatTime(combo.getHeatTime().longValue());
                    orderDetail.setStatus(PackageStatusEnums.WaitingToBeMade.getStatus());
                    orderDetail.setApplietAmount(combo.getSalePrice());
                    orderDetail.setDeviceAmount(combo.getSalePrice());
                    orderDetail.setAmount(combo.getSalePrice());
                    orderDetail.setThumbUrl(imgResource.getUrl());
                    orderDetail.setCompletedCount(0L);
                    orderDetail.setPickedUpCount(0L);
                    orderDetail.setCount(1L);
                    orderDetail.setCreateTime(timestamp);
                    orderDetail.setUpdateTime(timestamp);
                    orderDetails.add(orderDetail);


                    orderList = new OrderList();
                    orderList.setId(orderDetail.getOrderDetailId());
                    orderList.setOrderSn(orderCombo.getOrderId());
                    orderList.setOrderTime(timestamp);
                    orderList.setUserName(client.getNickName());
                    orderList.setUserMobile(client.getMobile());
                    orderList.setAmt(orderDetail.getAmount().toString());
                    orderList.setOriginalPrice(new BigDecimal(orderDetail.getApplietAmount()));
                    orderList.setPayType(PayTypeEnum.WeChatPay.getCode().toString());
                    orderList.setPayStatus(PayStatusEnum.PAID.getCode());
                    orderList.setComboId(combo.getComboId());
                    orderList.setComboName(combo.getName());
                    String tagIds = combo.getTagId();
                    List<String> tagIdList = StrUtil.split(tagIds, ",");
                    if (CollUtil.isNotEmpty(tagIdList)){
                        String tagNames = tagComboService.listByIds(tagIdList).stream().map(TagCombo::getTagName).collect(Collectors.joining(","));
                        orderList.setComboTag(tagNames);
                    }
                    orderList.setMachineId(orderCombo.getMachineId());
                    orderList.setCompanyId(machine.getCompanyId());
                    orderList.setCompanyName(company.getName());
                    orderList.setAreaId(machine.getAreaId());
                    orderList.setAreaName(area.getName());
                    orderList.setRouteId(machine.getRouteId());
                    orderList.setRouteName(route.getName());
                    orderList.setPayTime(new Timestamp(enterpriseOrder.getPayTime().getTime()));
                    orderList.setPositionId(machine.getPositionId());
                    orderList.setPositionName(position.getPositonName());
                    orderList.setPositionAddr(machine.getPositionAddr());
                    orderList.setIsException("1");
                    orderList.setOrderType(OrderTypeEnum.GOURP.getCode().toString());
                    orderList.setUpdateTime(timestamp);
                    orderList.setUpdateName(client.getNickName());
                    orderList.setCount(1L);
                    orderLists.add(orderList);
                }
            }
            // 更新订单数据
            orderComboService.save(orderCombo);
            orderDetailService.saveBatch(orderDetails);
            orderListService.saveBatch(orderLists);
            enterpriseOrderClientMapper.adds(enterpriseOrderClients);

        } catch (Exception e){
            e.printStackTrace();
        } finally {
            redisDistributedLock.unlock();
        }
        return ResponseEnum.OPERATOR_SUCCESS;
    }

    @Override
    public String findEnterpriseNameByEnterpriseId(Long enterpriseId) {
        return enterpriseOrderMapper.findEnterpriseNameByEnterpriseId(enterpriseId);
    }

    @Override
    public void updateFinishTime(String orderId) {
        enterpriseOrderMapper.updateFinishTime(orderId);
    }
}